﻿using System;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKPresentation.Utils;

namespace YJKPresentation.CommonUnit
{
	public class FindCurveInfo
	{
		public bool IsArc
		{
			get
			{
				return !Geometry.IsEqual(this.m_Bulge, 0.0);
			}
		}

		public XYZ StartPoint
		{
			get
			{
				return this.m_ptStart;
			}
		}

		public XYZ EndPoint
		{
			get
			{
				return this.m_ptEnd;
			}
		}

		public double Bulge
		{
			get
			{
				return this.m_Bulge;
			}
		}

		public XYZ Center
		{
			get
			{
				if (Geometry.IsEqual(this.m_Bulge, 0.0))
				{
					return null;
				}
				XYZ result = null;
				Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref result);
				return result;
			}
		}

		public bool SameAs(FindCurveInfo rhs)
		{
			return (this.m_ptStart.IsAlmostEqualTo(rhs.m_ptStart) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptEnd) && Geometry.IsEqual(this.m_Bulge, rhs.m_Bulge)) || (this.m_ptStart.IsAlmostEqualTo(rhs.m_ptEnd) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptStart) && Geometry.IsEqual(-this.m_Bulge, rhs.m_Bulge));
		}

		public bool IsEqual(FindCurveInfo rhs)
		{
			if (this.IsArc)
			{
				if (this.m_ptStart.IsAlmostEqualTo(rhs.m_ptStart) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptEnd) && Geometry.IsEqual(this.m_Bulge, rhs.m_Bulge))
				{
					return true;
				}
			}
			else
			{
				if (this.m_ptStart.IsAlmostEqualTo(rhs.m_ptStart) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptEnd))
				{
					return true;
				}
				if (this.m_ptStart.IsAlmostEqualTo(rhs.m_ptEnd) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptStart))
				{
					return true;
				}
			}
			return false;
		}

		public bool IsOverlap(FindCurveInfo rhs, XYZ point)
		{
			if (this.IsArc && rhs.IsArc)
			{
				XYZ xyz = null;
				XYZ xyz2 = null;
				Geometry.OverlapType overlapType = Geometry.IsOverlapOfTwoArc(this.Point2D(this.StartPoint), this.Point2D(this.EndPoint), this.Point2D(this.Center), this.Point2D(rhs.StartPoint), this.Point2D(rhs.EndPoint), this.Point2D(rhs.Center), ref xyz, ref xyz2);
				if (overlapType != Geometry.OverlapType._OT_None && overlapType != Geometry.OverlapType._OT_Linked && this.IncludPoint(point))
				{
					return true;
				}
			}
			else if (!this.IsArc && !rhs.IsArc)
			{
				XYZ xyz3 = null;
				XYZ xyz4 = null;
				Geometry.OverlapType overlapType2 = Geometry.IsOverlapOfTwoLine(this.Point2D(this.StartPoint), this.Point2D(this.EndPoint), this.Point2D(rhs.StartPoint), this.Point2D(rhs.EndPoint), ref xyz3, ref xyz4);
				if (overlapType2 != Geometry.OverlapType._OT_None && overlapType2 != Geometry.OverlapType._OT_Linked && this.IncludPoint(point))
				{
					return true;
				}
			}
			return false;
		}

		private XYZ Point2D(XYZ point)
		{
			return new XYZ(point.X, point.Y, 0.0);
		}

		private bool IncludPoint(XYZ pt)
		{
			XYZ point = this.Point2D(pt);
			XYZ xyz = this.Point2D(this.StartPoint);
			XYZ xyz2 = this.Point2D(this.EndPoint);
			if (this.IsArc)
			{
				XYZ xyz3 = this.Point2D(this.Center);
				XYZ xyz4 = XYZ.BasisZ;
				if (Geometry.LessThan(this.Bulge, 0.0))
				{
					xyz4 = -xyz4;
				}
				XYZ pt2 = Geometry.CalculateFootPoint(xyz, xyz2, xyz3, point);
				if (Geometry.Is_Point_OnSegment(xyz, xyz2, xyz3, xyz4, pt2))
				{
					return true;
				}
			}
			else
			{
				XYZ pt3 = Geometry.CalculateFootPoint(xyz, xyz2, point);
				if (Geometry.Is_Point_OnSegment(xyz, xyz2, pt3))
				{
					return true;
				}
			}
			return false;
		}

		public bool IsParallel2ndOverlap(FindCurveInfo rhs, XYZ pt, ref double offset)
		{
			XYZ pt2 = this.Point2D(pt);
			XYZ xyz = this.Point2D(this.StartPoint);
			XYZ xyz2 = this.Point2D(this.EndPoint);
			XYZ xyz3 = this.Point2D(rhs.StartPoint);
			XYZ xyz4 = this.Point2D(rhs.EndPoint);
			if (this.IsArc && rhs.IsArc)
			{
				XYZ center = rhs.Center;
				XYZ center2 = this.Center;
				if (center.IsAlmostEqualTo(center2))
				{
					double num = this.Center.DistanceTo(xyz);
					double num2 = center.DistanceTo(xyz3);
					FindCurveInfo findCurveInfo = new FindCurveInfo(this);
					findCurveInfo.m_ptStart = center2 + (xyz - center2).Normalize() * num2;
					findCurveInfo.m_ptEnd = center2 + (xyz2 - center2).Normalize() * num2;
					XYZ xyz5 = null;
					XYZ xyz6 = null;
					Geometry.OverlapType overlapType = Geometry.IsOverlapOfTwoArc(this.Point2D(xyz3), this.Point2D(xyz4), this.Point2D(center), this.Point2D(findCurveInfo.StartPoint), this.Point2D(findCurveInfo.EndPoint), this.Point2D(center2), ref xyz5, ref xyz6);
					if (overlapType != Geometry.OverlapType._OT_None && overlapType != Geometry.OverlapType._OT_Linked && findCurveInfo.IncludPoint(pt2))
					{
						offset = Math.Abs(num - num2);
						return true;
					}
				}
			}
			else if (!this.IsArc && !rhs.IsArc && Geometry.IsParallel(xyz3 - xyz4, xyz - xyz2))
			{
				XYZ xyz7 = Geometry.CalculateFootPoint(xyz3, xyz4, xyz) - xyz;
				FindCurveInfo findCurveInfo2 = new FindCurveInfo(this);
				findCurveInfo2.m_ptStart += xyz7;
				findCurveInfo2.m_ptEnd += xyz7;
				XYZ xyz8 = null;
				XYZ xyz9 = null;
				Geometry.OverlapType overlapType2 = Geometry.IsOverlapOfTwoLine(this.Point2D(xyz3), this.Point2D(xyz4), this.Point2D(findCurveInfo2.StartPoint), this.Point2D(findCurveInfo2.EndPoint), ref xyz8, ref xyz9);
				if (overlapType2 != Geometry.OverlapType._OT_None && overlapType2 != Geometry.OverlapType._OT_Linked && findCurveInfo2.IncludPoint(pt2))
				{
					offset = xyz7.GetLength();
					return true;
				}
			}
			return false;
		}

		public XYZ GetOffset(FindCurveInfo rhs, XYZ testPoint)
		{
			XYZ result = null;
			if (this.IsArc && rhs.IsArc)
			{
				double num = rhs.Center.DistanceTo(rhs.StartPoint);
				double num2 = this.Center.DistanceTo(this.StartPoint);
				double num3 = num - num2;
				return (testPoint - this.Center).Normalize() * num3;
			}
			if (!this.IsArc && !rhs.IsArc)
			{
				result = Geometry.CalculateFootPoint(rhs.StartPoint, rhs.EndPoint, this.StartPoint) - this.StartPoint;
			}
			return result;
		}

		public FindCurveInfo(FindCurveInfo rhs)
		{
			this.m_ptStart = rhs.m_ptStart;
			this.m_ptEnd = rhs.m_ptEnd;
			this.m_Bulge = rhs.m_Bulge;
		}

		public FindCurveInfo(XYZ ptStart, XYZ ptEnd, double bulge)
		{
			this.m_ptStart = ptStart;
			this.m_ptEnd = ptEnd;
			this.m_Bulge = bulge;
		}

		public FindCurveInfo(Curve curve)
		{
			XYZ hyendPoint = curve.GetEndPoint(0);
			XYZ hyendPoint2 = curve.GetEndPoint(1);
			Line line = curve as Line;
			if (null != line)
			{
				this.m_ptStart = hyendPoint;
				this.m_ptEnd = hyendPoint2;
				this.m_Bulge = 0.0;
			}
			Arc arc = curve as Arc;
			if (null != arc)
			{
				if (!arc.Normal.IsAlmostEqualTo(XYZ.BasisZ))
				{
					hyendPoint = curve.GetEndPoint(1);
					hyendPoint2 = curve.GetEndPoint(0);
				}
				double bulge = Geometry.GetBulge(hyendPoint, hyendPoint2, arc.Center, true);
				this.m_ptStart = hyendPoint;
				this.m_ptEnd = hyendPoint2;
				this.m_Bulge = bulge;
			}
		}

		private XYZ m_ptStart;

		private XYZ m_ptEnd;

		private double m_Bulge;
	}
}
